package GUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;

import Statistics.IDGraphToJungGraph.MyEdge;
import Statistics.IDGraphToJungGraph.MyNode;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.KKLayout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.GraphMouseListener;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.AbstractVertexShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner;

public class SCCViewDialog extends JDialog {
	String seed = null;
    DirectedSparseGraph<String, MyEdge> graph;
    VisualizationViewer<String, MyEdge> vv;
    
    public SCCViewDialog(String title,final DirectedSparseGraph<String, MyEdge> graph,final String seed)
    {
    	super();
    	this.seed = seed;
    	setTitle(title);
        // create a simple graph for the demo
        this.graph = graph;
        
        //ImageIcon sandstoneIcon = null;
        //String imageLocation = "/images/Sandstone.jpg";
//        try {
//            	sandstoneIcon = 
//            	    new ImageIcon(getClass().getResource(imageLocation));
//        } catch(Exception ex) {
//            System.err.println("Can't load \""+imageLocation+"\"");
//        }
//        final ImageIcon icon = sandstoneIcon;
		FRLayout<String, MyEdge> layout = new FRLayout<String, MyEdge>(graph);
		layout.setMaxIterations(500);
        vv =  new VisualizationViewer<String,MyEdge>(layout);
        vv.setBackground(Color.black);
//        if(icon != null) {
//            vv.addPreRenderPaintable(new VisualizationViewer.Paintable(){
//                public void paint(Graphics g) {
//                    Dimension d = vv.getSize();
//                    g.drawImage(icon.getImage(),0,0,d.width,d.height,vv);
//                }
//                public boolean useTransform() { return false; }
//            });
//        }
        vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){
            int x;
            int y;
            Font font;
            FontMetrics metrics;
            int swidth;
            int sheight;
            String str = "Local View of the IDGraph";
            
            public void paint(Graphics g) {
                Dimension d = vv.getSize();
                if(font == null) {
                    font = new Font(g.getFont().getName(), Font.BOLD, 30);
                    metrics = g.getFontMetrics(font);
                    swidth = metrics.stringWidth(str);
                    sheight = metrics.getMaxAscent()+metrics.getMaxDescent();
                    x = (d.width-swidth-10)/2;
                    y = (int)(d.height-sheight);
                }
                g.setFont(font);
                Color oldColor = g.getColor();
                g.setColor(Color.yellow);
                g.drawString(str, x, y);
                g.setColor(oldColor);
            }
            public boolean useTransform() {
                return false;
            }
        });

        vv.addGraphMouseListener(new TestGraphMouseListener<String>());

        vv.getRenderer().setVertexRenderer(
        		new GradientVertexRenderer<String,MyEdge>(
        				Color.white, Color.red, 
        				Color.white, Color.blue,
        				vv.getPickedVertexState(),
        				false));
//		vv.getRenderContext().setVertexFillPaintTransformer(
//				new Transformer<String, Paint>() {
//					public Paint transform(String v) {
//						if (v.equals(seed))
//							return Color.white;
//						else
//							return Color.red;
//					}
//				});
        vv.getRenderContext().setEdgeDrawPaintTransformer(new ConstantTransformer(Color.red));
        vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.black));
        vv.getRenderContext().setArrowDrawPaintTransformer(new ConstantTransformer(Color.lightGray));
        vv.getRenderContext().setVertexShapeTransformer(new VertexShapeSizeAspect<String,MyEdge>(graph));
        
        // add my listeners for ToolTips
        vv.setVertexToolTipTransformer(new ToStringLabeller<String>());
        vv.setEdgeToolTipTransformer(new Transformer<MyEdge,String>() {
			public String transform(MyEdge edge) {
				return "E"+graph.getEndpoints(edge).toString();
			}});
        
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<String>());
        vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner());
        vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO);
        vv.setForeground(Color.lightGray);
        
        // create a frome to hold the graph

        Container content = getContentPane();
        final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
        content.add(panel);
    
        final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse<String,Number>();
        vv.setGraphMouse(graphMouse);
        
        vv.addKeyListener(graphMouse.getModeKeyListener());
        vv.setToolTipText("<html><center>Type 'p' for Pick mode<p>Type 't' for Transform mode");
        
        final ScalingControl scaler = new CrossoverScalingControl();

        JButton plus = new JButton("+");
        plus.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1.1f, vv.getCenter());
            }
        });
        JButton minus = new JButton("-");
        minus.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1/1.1f, vv.getCenter());
            }
        });

        JButton reset = new JButton("reset");
        reset.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
				vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity();
			}});

        JPanel controls = new JPanel();
        controls.add(plus);
        controls.add(minus);
        controls.add(reset);
        content.add(controls, BorderLayout.SOUTH);
    }

	private static class VertexShapeSizeAspect<V, E> extends
			AbstractVertexShapeTransformer<V> implements Transformer<V, Shape> {
		private static int minVertexSize = 2;

		public VertexShapeSizeAspect(final Graph<String, MyEdge> graph) {
			setSizeTransformer(new Transformer<V, Integer>() {
				public Integer transform(V v) {
					int  para = graph.getOutEdges((String) v).size() + 1;
					return 20+para*2 ;
				}
			});
		}

		public Shape transform(V v) {
			return factory.getEllipse(v);
		}
	}

    /**
     * A nested class to demo the GraphMouseListener finding the
     * right vertices after zoom/pan
     */
    static class TestGraphMouseListener<V> implements GraphMouseListener<V> {
        
    		public void graphClicked(V v, MouseEvent me) {
    		    System.err.println("Vertex "+v+" was clicked at ("+me.getX()+","+me.getY()+")");
    		}
    		public void graphPressed(V v, MouseEvent me) {
    		    System.err.println("Vertex "+v+" was pressed at ("+me.getX()+","+me.getY()+")");
    		}
    		public void graphReleased(V v, MouseEvent me) {
    		    System.err.println("Vertex "+v+" was released at ("+me.getX()+","+me.getY()+")");
    		}
    }

}
